// license-header java merge-point
/**
 * This is only generated once! It will never be overwritten. You can (and have to!) safely modify it by hand.
 */
package org.tinaelle.server.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import org.tinaelle.ServiceLocator;
import org.tinaelle.common.dto.AdGroupDTO;
import org.tinaelle.common.dto.AdRoleDTO;
import org.tinaelle.common.dto.AdRoleScreensDTO;
import org.tinaelle.common.dto.AdScreenDTO;
import org.tinaelle.common.dto.AdSessionDTO;
import org.tinaelle.common.dto.AdUserDTO;
import org.tinaelle.common.dto.AdUserGroupsDTO;
import org.tinaelle.common.dto.AdUserRolesDTO;
import org.tinaelle.exceptions.UserInputException;
import org.tinaelle.server.domain.AdGroup;
import org.tinaelle.server.domain.AdGroupDao;
import org.tinaelle.server.domain.AdRole;
import org.tinaelle.server.domain.AdRoleDao;
import org.tinaelle.server.domain.AdRoleScreens;
import org.tinaelle.server.domain.AdScreen;
import org.tinaelle.server.domain.AdUser;
import org.tinaelle.server.domain.AdUserDao;
import org.tinaelle.server.domain.AdUserGroups;
import org.tinaelle.server.domain.AdUserRoles;
import org.tinaelle.utils.BootstrapUtils;
import org.tinaelle.utils.Session;

/**
 * @see org.tinaelle.service.AdSecurityService
 */
public class AdSecurityServiceImpl extends org.tinaelle.server.service.AdSecurityServiceBase {

	/**
     * 
     */
	private static final long	serialVersionUID	= 1L;

	/**
	 * @see org.tinaelle.service.AdSecurityService#login(java.lang.String, java.lang.String)
	 */
	@Override
	protected Boolean handleLogin(final java.lang.String email, final java.lang.String password)
	        throws java.lang.Exception {
		final AdUserDTO u = ( AdUserDTO ) getAdUserDao().findByEmail( AdUserDao.TRANSFORM_ADUSERDTO, email );

		if ( u == null ) {
			throw new UserInputException( "Login does not exits" );
		}

		if ( !u.getPassword().equals( password ) ) {
			throw new UserInputException( "Login incorrect" );
		}

		if ( !u.isIsActive() ) {
			throw new UserInputException( "User is not active" );
		}

		AdSessionDTO s = new AdSessionDTO();
		s.setLogin( new Date() );
		s.setAdUserId( u.getAdUserId() );
		s = ServiceLocator.instance().getAdSystemService().save( s );

		Session.get().setUser( u );
		Session.get().setSession( s );

		return Boolean.TRUE;
		// return s;
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#logout()
	 */
	@Override
	protected org.tinaelle.common.dto.AdUserDTO handleLogout() throws java.lang.Exception {
		final Session s = Session.get();
		s.resetUser();
		final AdSessionDTO session = s.getSession();
		s.resetSession();
		session.setLogout( new Date() );
		ServiceLocator.instance().getAdSystemService().save( session );
		return s.getUser();
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#getLoggedInUser()
	 */
	@Override
	protected org.tinaelle.common.dto.AdUserDTO handleGetLoggedInUser() throws java.lang.Exception {
		return Session.get().getUser();
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#getUsers(org.tinaelle.common.dto.AdGroupDTO)
	 */
	@Override
	protected org.tinaelle.common.dto.AdUserDTO[] handleGetUsers(final org.tinaelle.common.dto.AdGroupDTO adGroupDTO)
	        throws java.lang.Exception {
		final AdGroup adGroup = ( AdGroup ) getAdGroupDao().load( AdGroupDao.TRANSFORM_NONE, adGroupDTO.getAdGroupId() );
		final ArrayList<AdUser> adUsers = new ArrayList<AdUser>();
		final Collection<AdUserGroups> adUserGroups = adGroup.getAdUserGroups();
		for ( final Iterator<AdUserGroups> i = adUserGroups.iterator(); i.hasNext(); ) {
			final AdUserGroups userGroup = i.next();
			adUsers.add( userGroup.getAdUser() );
		}
		getAdUserDao().toAdUserDTOCollection( adUsers );

		return adUsers.toArray( new AdUserDTO[ 0 ] );
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#getGroups(org.tinaelle.common.dto.AdUserDTO)
	 */
	@Override
	protected org.tinaelle.common.dto.AdGroupDTO[] handleGetGroups(final org.tinaelle.common.dto.AdUserDTO adUserDTO)
	        throws java.lang.Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final ArrayList<AdGroup> adGroups = new ArrayList<AdGroup>();
		final Collection<AdUserGroups> adUserGroups = adUser.getAdUserGroups();
		for ( final Iterator<AdUserGroups> i = adUserGroups.iterator(); i.hasNext(); ) {
			final AdUserGroups userGroup = i.next();
			adGroups.add( userGroup.getAdGroup() );
		}
		getAdGroupDao().toAdGroupDTOCollection( adGroups );

		return adGroups.toArray( new AdGroupDTO[ 0 ] );
	}

	@Override
	protected AdRoleDTO[] handleGetRoles(final AdUserDTO adUserDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final ArrayList<AdRole> adRoles = new ArrayList<AdRole>();
		final Collection<AdUserRoles> adUserRoles = adUser.getAdUserRoles();
		for ( final Iterator<AdUserRoles> i = adUserRoles.iterator(); i.hasNext(); ) {
			final AdUserRoles userRole = i.next();
			adRoles.add( userRole.getAdRole() );
		}
		getAdRoleDao().toAdRoleDTOCollection( adRoles );

		return adRoles.toArray( new AdRoleDTO[ 0 ] );
	}

	@Override
	protected AdScreenDTO[] handleGetScreens(final AdRoleDTO adRoleDTO) throws Exception {
		final AdRole adRole = ( AdRole ) getAdRoleDao().load( AdRoleDao.TRANSFORM_NONE, adRoleDTO.getAdRoleId() );
		final ArrayList<AdScreen> adScreens = new ArrayList<AdScreen>();
		final Collection<AdRoleScreens> adRoleScreens = adRole.getAdRoleScreens();
		for ( final Iterator<AdRoleScreens> i = adRoleScreens.iterator(); i.hasNext(); ) {
			final AdRoleScreens userRole = i.next();
			adScreens.add( userRole.getAdScreen() );
		}
		getAdScreenDao().toAdScreenDTOCollection( adScreens );

		return adScreens.toArray( new AdScreenDTO[ 0 ] );
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#addUserToGroup(org.tinaelle.common.dto.AdUserDTO,
	 *      org.tinaelle.common.dto.AdGroupDTO)
	 */
	@Override
	protected void handleAddUserToGroup(final org.tinaelle.common.dto.AdUserDTO adUserDTO,
	        final org.tinaelle.common.dto.AdGroupDTO adGroupDTO) throws java.lang.Exception {
		final AdUserGroupsDTO userGroupDTO = new AdUserGroupsDTO();

		userGroupDTO.setAdGroupId( adGroupDTO.getAdGroupId() );
		userGroupDTO.setAdUserId( adUserDTO.getAdUserId() );

		save( userGroupDTO );
	}

	@Override
	protected void handleAddRoleToScreen(final AdRoleDTO adRoleDTO, final AdScreenDTO adScreenDTO) throws Exception {
		final AdRoleScreensDTO roleScreensDTO = new AdRoleScreensDTO();

		roleScreensDTO.setAdRoleId( adRoleDTO.getAdRoleId() );
		roleScreensDTO.setAdScreenId( adScreenDTO.getAdScreenId() );

		save( roleScreensDTO );
	}

	@Override
	protected void handleAddUserToRole(final AdUserDTO adUserDTO, final AdRoleDTO adRoleDTO) throws Exception {
		final AdUserRolesDTO userRoleDTO = new AdUserRolesDTO();

		userRoleDTO.setAdRoleId( adRoleDTO.getAdRoleId() );
		userRoleDTO.setAdUserId( adUserDTO.getAdUserId() );

		save( userRoleDTO );
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#removeUserFromGroup(org.tinaelle.common.dto.AdUserDTO,
	 *      org.tinaelle.common.dto.AdGroupDTO)
	 */
	@Override
	protected void handleRemoveUserFromGroup(final org.tinaelle.common.dto.AdUserDTO adUserDTO,
	        final org.tinaelle.common.dto.AdGroupDTO adGroupDTO) throws java.lang.Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );

		final Collection<AdUserGroups> userGroups = adUser.getAdUserGroups();
		for ( final Iterator<AdUserGroups> i = userGroups.iterator(); i.hasNext(); ) {
			final AdUserGroups userGroup = i.next();
			if ( userGroup.getAdGroup().getAdGroupId().equals( adGroupDTO.getAdGroupId() ) ) {
				getAdUserGroupsDao().remove( userGroup );
				return;
			}
		}
	}

	@Override
	protected void handleRemoveRoleFromScreen(final AdRoleDTO adRoleDTO, final AdScreenDTO adScreenDTO)
	        throws Exception {
		final AdRole adRole = ( AdRole ) getAdRoleDao().load( AdRoleDao.TRANSFORM_NONE, adRoleDTO.getAdRoleId() );

		final Collection<AdRoleScreens> userScreens = adRole.getAdRoleScreens();
		for ( final Iterator<AdRoleScreens> i = userScreens.iterator(); i.hasNext(); ) {
			final AdRoleScreens userScreen = i.next();
			if ( userScreen.getAdScreen().getAdScreenId().equals( adScreenDTO.getAdScreenId() ) ) {
				getAdRoleScreensDao().remove( userScreen );
				return;
			}
		}
	}

	@Override
	protected void handleRemoveUserFromRole(final AdUserDTO adUserDTO, final AdRoleDTO adRoleDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );

		final Collection<AdUserRoles> userRoles = adUser.getAdUserRoles();
		for ( final Iterator<AdUserRoles> i = userRoles.iterator(); i.hasNext(); ) {
			final AdUserRoles userRole = i.next();
			if ( userRole.getAdRole().getAdRoleId().equals( adRoleDTO.getAdRoleId() ) ) {
				getAdUserRolesDao().remove( userRole );
				return;
			}
		}
	}

	@Override
	protected boolean handleIsMemberOf(final AdUserDTO adUserDTO, final AdGroupDTO adGroupDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final Collection<AdUserGroups> userGroups = adUser.getAdUserGroups();
		for ( final Iterator<AdUserGroups> i = userGroups.iterator(); i.hasNext(); ) {
			final AdUserGroups userGroup = i.next();
			if ( userGroup.getAdGroup().getAdGroupId().equals( adGroupDTO.getAdGroupId() ) ) {
				return true;
			}
		}
		return false;
	}

	@Override
	protected boolean handleIsMemberOf(final AdUserDTO adUserDTO, final AdRoleDTO adRoleDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final Collection<AdUserRoles> userRoles = adUser.getAdUserRoles();
		for ( final Iterator<AdUserRoles> i = userRoles.iterator(); i.hasNext(); ) {
			final AdUserRoles userRole = i.next();
			if ( userRole.getAdRole().getAdRoleId().equals( adRoleDTO.getAdRoleId() ) ) {
				return true;
			}
		}
		return false;
	}

	@Override
	protected boolean handleHasAccess(final AdUserDTO adUserDTO, final AdScreenDTO adScreenDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final Collection<AdUserRoles> userRoles = adUser.getAdUserRoles();
		for ( final Iterator<AdUserRoles> i = userRoles.iterator(); i.hasNext(); ) {
			final AdUserRoles userRole = i.next();
			final AdRole role = userRole.getAdRole();
			final Collection<AdRoleScreens> roleScreens = role.getAdRoleScreens();
			for ( final Iterator<AdRoleScreens> j = roleScreens.iterator(); j.hasNext(); ) {
				final AdRoleScreens roleScreen = j.next();
				if ( roleScreen.getAdScreen().getAdScreenId().equals( adScreenDTO.getAdScreenId() ) ) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	protected boolean handleHasReadAccess(final AdUserDTO adUserDTO, final AdScreenDTO adScreenDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final Collection<AdUserRoles> userRoles = adUser.getAdUserRoles();
		for ( final Iterator<AdUserRoles> i = userRoles.iterator(); i.hasNext(); ) {
			final AdUserRoles userRole = i.next();
			final AdRole role = userRole.getAdRole();
			final Collection<AdRoleScreens> roleScreens = role.getAdRoleScreens();
			for ( final Iterator<AdRoleScreens> j = roleScreens.iterator(); j.hasNext(); ) {
				final AdRoleScreens roleScreen = j.next();
				if ( roleScreen.getAdScreen().getAdScreenId().equals( adScreenDTO.getAdScreenId() )
				        && roleScreen.isIsReadAccess() ) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	protected boolean handleHasWriteAccess(final AdUserDTO adUserDTO, final AdScreenDTO adScreenDTO) throws Exception {
		final AdUser adUser = ( AdUser ) getAdUserDao().load( AdUserDao.TRANSFORM_NONE, adUserDTO.getAdUserId() );
		final Collection<AdUserRoles> userRoles = adUser.getAdUserRoles();
		for ( final Iterator<AdUserRoles> i = userRoles.iterator(); i.hasNext(); ) {
			final AdUserRoles userRole = i.next();
			final AdRole role = userRole.getAdRole();
			final Collection<AdRoleScreens> roleScreens = role.getAdRoleScreens();
			for ( final Iterator<AdRoleScreens> j = roleScreens.iterator(); j.hasNext(); ) {
				final AdRoleScreens roleScreen = j.next();
				if ( roleScreen.getAdScreen().getAdScreenId().equals( adScreenDTO.getAdScreenId() )
				        && roleScreen.isIsWriteAccess() ) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	protected AdGroupDTO handleGetGroupByName(final String name) throws Exception {
		return ( AdGroupDTO ) getAdGroupDao().findByName( AdGroupDao.TRANSFORM_ADGROUPDTO, name );
	}

	@Override
	protected AdUserDTO handleGetUserByEmail(final String email) throws Exception {
		return ( AdUserDTO ) getAdUserDao().findByEmail( AdUserDao.TRANSFORM_ADUSERDTO, email );
	}

	@Override
	protected AdRoleDTO handleGetRoleByName(final String name) throws Exception {
		return ( AdRoleDTO ) getAdRoleDao().findByName( AdRoleDao.TRANSFORM_ADROLEDTO, name );
	}

	@Override
	protected AdUserDTO handleGetUserByNickname(final String nickname) throws Exception {
		return ( AdUserDTO ) getAdUserDao().findByNickname( AdUserDao.TRANSFORM_ADUSERDTO, nickname );
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#fillInitialValues()
	 */
	@Override
	protected void handleFillInitialValues() throws java.lang.Exception {
		/**
		 * Load Users
		 */
		fillInitialValuesForUser();

		/**
		 * Load Groups
		 */
		fillInitialValuesForGroup();

		/**
		 * Load Roles
		 */
		fillInitialValuesForRole();
	}

	/**
	 * @see org.tinaelle.service.AdSecurityService#fillDummyValues()
	 */
	@Override
	protected void handleFillDummyValues() throws java.lang.Exception {
		final AdGroupDTO recruiterGroup = getGroupByName( "Recruiters" );

		AdUserDTO fooRecruiter = getUserByEmail( "Foo.Recruiter@ilem.ma" );
		if ( fooRecruiter == null ) {
			fooRecruiter = new AdUserDTO();
			fooRecruiter.setEmail( "Foo.Recruiter@ilem.ma" );
			fooRecruiter.setFirstName( "Foo" );
			fooRecruiter.setLastName( "Recruiter" );
			fooRecruiter.setPassword( "none2007" );
			save( fooRecruiter );
		}

		if ( !isMemberOf( fooRecruiter, recruiterGroup ) ) {
			addUserToGroup( fooRecruiter, recruiterGroup );
		}

		final AdGroupDTO candidateGroup = getGroupByName( "Candidates" );
		AdUserDTO fooCandiate = getUserByEmail( "Foo.Candiate@ilem.ma" );
		if ( fooCandiate == null ) {
			fooCandiate = new AdUserDTO();
			fooCandiate.setEmail( "Foo.Candiate@ilem.ma" );
			fooCandiate.setFirstName( "Foo" );
			fooCandiate.setLastName( "Candidate" );
			fooCandiate.setPassword( "none2007" );
			save( fooCandiate );
		}

		if ( !isMemberOf( fooCandiate, candidateGroup ) ) {
			addUserToGroup( fooCandiate, candidateGroup );
		}

		final AdGroupDTO companyGroup = getGroupByName( "Companies" );
		AdUserDTO fooCompany = getUserByEmail( "Foo.Company@ilem.ma" );
		if ( fooCompany == null ) {
			fooCompany = new AdUserDTO();
			fooCompany.setEmail( "Foo.Company@ilem.ma" );
			fooCompany.setFirstName( "Foo" );
			fooCompany.setLastName( "Company" );
			fooCompany.setPassword( "none2007" );
			save( fooCompany );
		}
		if ( !isMemberOf( fooCompany, companyGroup ) ) {
			addUserToGroup( fooCompany, companyGroup );
		}
	}

	@Override
	protected void handleFillInitialValuesForGroup() throws Exception {
		// File Format :
		// Name, Description, Users : 0, 1, 2
		String[][] groupContent = BootstrapUtils.instance().getBootstrapSheetContent( "AdGroup" );
		for ( int i = 1; i < groupContent.length; i++ ) {
			final String[] groupLine = groupContent[ i ];

			if ( groupLine.length > 1 ) {
				AdGroupDTO adGroupDTO = getGroupByName( groupLine[ 0 ] );
				if ( adGroupDTO == null ) {
					adGroupDTO = new AdGroupDTO();
				}

				adGroupDTO.setName( groupLine[ 0 ] );
				adGroupDTO.setDescription( groupLine[ 1 ] );

				adGroupDTO = save( adGroupDTO );

				if ( groupLine.length > 2 ) {
					final String[] users = groupLine[ 2 ].split( "," );
					for ( int j = 0; j < users.length; j++ ) {
						final AdUserDTO adUserDTO = getUserByNickname( users[ j ] );
						addUserToGroup( adUserDTO, adGroupDTO );
					}
				}
			}
		}
	}

	@Override
	protected void handleFillInitialValuesForRole() throws Exception {
		// File Format :
		// Name, Description, Users : 0, 1, 2
		// Screens : 4
		String[][] roleContent = BootstrapUtils.instance().getBootstrapSheetContent( "AdRole" );
		for ( int i = 1; i < roleContent.length; i++ ) {
			final String[] roleLine = roleContent[ i ];

			if ( roleLine.length > 1 ) {
				AdRoleDTO adRoleDTO = getRoleByName( roleLine[ 0 ] );
				if ( adRoleDTO == null ) {
					adRoleDTO = new AdRoleDTO();
				}

				adRoleDTO.setName( roleLine[ 0 ] );
				adRoleDTO.setDescription( roleLine[ 1 ] );

				adRoleDTO = save( adRoleDTO );

				if ( roleLine.length > 2 ) {
					final String[] users = roleLine[ 2 ].split( "," );
					for ( int j = 0; j < users.length; j++ ) {
						final AdUserDTO adUserDTO = getUserByNickname( users[ j ] );
						addUserToRole( adUserDTO, adRoleDTO );
					}
				}
				if ( roleLine.length > 3 ) {
					final String[] screens = roleLine[ 3 ].split( "," );
					for ( int j = 0; j < screens.length; j++ ) {
						final AdScreenDTO adScreenDTO = ServiceLocator.instance().getAdWindowService().getScreenByName(
						        screens[ j ] );
						addRoleToScreen( adRoleDTO, adScreenDTO );
					}
				}
			}
		}
	}

	@Override
	protected void handleFillInitialValuesForUser() throws Exception {
		// File Format :
		// EMail, First Name, Last Name : 0, 1, 2
		// Nickname, Password : 3, 4
		String[][] userContent = BootstrapUtils.instance().getBootstrapSheetContent( "AdUser" );
		for ( int i = 1; i < userContent.length; i++ ) {
			final String[] userLine = userContent[ i ];
			if ( userLine.length > 4 ) {
				AdUserDTO adUserDTO = getUserByEmail( userLine[ 0 ] );
				if ( adUserDTO == null ) {
					adUserDTO = new AdUserDTO();
				}

				adUserDTO.setEmail( userLine[ 0 ] );
				adUserDTO.setFirstName( userLine[ 1 ] );
				adUserDTO.setLastName( userLine[ 2 ] );
				adUserDTO.setNickname( userLine[ 3 ] );
				adUserDTO.setPassword( userLine[ 4 ] );

				adUserDTO = save( adUserDTO );
			}
		}
	}

}